<template>
	<Editor
		:id="id"
		:inline="true"
		@onInit="handleInit"
		:init="config"
		ref="zcoInput"
		:style="{ pointerEvents: showDetail ? 'none' : 'auto' }"
		class="tinymce-input"
		@keydown.native="handleKeydown"
		@keyup.native="handleKeydown"
	/>
</template>

<script>
const ZCO_TAG = `<span class="mceNonEditable el-tag el-tag--info el-tag--light">ZCO_TAG_TEXT1<span class="mce-hide">ZCO_TAG_TEXT2</span>}}</span>`;
const ZCO_TAG_2 = `<span class="mceNonEditable el-tag el-tag--info el-tag--light">ZCO_TAG_TEXT1</span>`;
// &#xFEFF;
const ZCO_BEGIN_TAG = `&#xFEFF;`; // '\u00A0' `\n`
// const ZCO_END_TAG = `\u00A0`; // '\u00A0' `\n`

import { mapState, mapActions } from 'vuex';
// import tinymce from "tinymce"; // tinymce.min.js
import Editor from '@tinymce/tinymce-vue';
// We're manually importing theme, icons and plugins because otherwise TinyMCE tries to resolve
// them himself and load throught http, but this won't work with chrome extension
// Theme
// import "tinymce/themes/silver/theme.min.js";
// import "tinymce/models/dom/model.js";
// import "tinymce/icons/default/icons.js";
/* Import content css */
import {contentUiCss} from '../tinycss/ui/oxide/content.js';
import {contentCss} from '../tinycss/content/default/content.js';
const config = {
	height: '36',
	min_height: 36,
	menubar: false,
	plugins: [], // wordcount
	toolbar: false,
	inline: true,
	noneditable_class: 'mceNonEditable',
	skin: false,
	content_css: false,
	// content_style: contentUiCss.toString() + "\n" + contentCss.toString(),
	nowrap: true,
	force_root_block: ''
	// forced_root_block: 'div'
};

window.tinymce = tinymce;

export default {
	components: { Editor },
	props: {
		value: {
			type: String,
			default: () => ''
		},
		id: {
			type: String,
			default: () => ''
		},
		required: {
			type: Boolean,
			default: () => false
		},
		minlength: {
			type: Number,
			default: () => 1
		},
		maxlength: {
			type: Number,
			default: () => 140
		},
		showDetail: {
			type: Boolean,
			default: () => false
		},
		placeholder: {
			type: String,
			default: () => ''
		},
		autosize: {
			type: Object,
			default: () => ({ minRows: 1.1, maxRows: 3 })
		}
	},
	watch: {
		insert(newVal) {
			const { id, variable } = newVal || {};
			if (id === this.$refs.zcoInput.id) {
				this.insertKeyword(variable, true);
			}
		},
		value(newVal) {
			if (!this.editor) return;
			if (newVal) {
				if (this.editor.getContent({ format: 'text' }) !== newVal) {
					this.editor.setContent('');
					this.parse(newVal);
				}
			} else {
				this.editor.setContent('');
			}
		},
		showDetail(newVal) {
			this.editor.mode.set(newVal ? 'readonly' : 'design');
		}
	},

	computed: {
		...mapState({
			insert: state => state.variable.insert
		})
	},

	data() {
		return {
			editor: null,
			config: {
				...config,
				placeholder: this.placeholder,
				max_chars: this.maxlength,
				readonly: this.showDetail ? 1 : 0,
				content_style: contentUiCss+ '\n' + contentCss,
			},
			parsedValue: ''
		};
	},

	mounted() {
		// console.log("mounted", this.value);
		this.$nextTick(() => {
			this.parse(this.value);
		});
	},
	beforeDestroy() {},

	methods: {
		...mapActions('variable', ['setInsertVariable']),

		findNextEditableNode(node, next) {
			let currentNode = next ? node.nextSibling : node.previousSibling; // nextSibling
			while (currentNode) {
				if (currentNode.nodeType === 3 && currentNode.tagName !== 'SPAN') {
					return currentNode;
				}
				currentNode = next ? currentNode.nextSibling : currentNode.previousSibling;
			}

			return null;
		},

		handleKeydown(e) {
			if (e.keyCode === 13) {
				e.preventDefault();
				e.stopPropagation();
				e.stopImmediatePropagation();
				return false;
			}
			var allowedKeys = [8, 16, 17, 18, 20, 33, 34, 35, 36, 38, 40, 46];
			if (allowedKeys.indexOf(e.keyCode) != -1) return true;
			if (e.ctrlKey) return true;

			if ([37, 39].includes(e.keyCode) && this.editor.selection.getNode().tagName === 'SPAN') {
				// 左箭头按键的键码
				e.preventDefault(); // 阻止默认行为
				e.stopPropagation();
				e.stopImmediatePropagation();
				// 找到下一个可编辑的节点
				const next = e.keyCode === 39;
				let nextEditableNode = this.findNextEditableNode(this.editor.selection.getNode(), next);
        
				if (nextEditableNode) {
					this.editor.selection.setCursorLocation(nextEditableNode, next ? 0 : nextEditableNode.textContent.length);
					return false;
				} else if (next) {
					let node = this.editor.selection.getNode().parentNode;
					this.editor.selection.setCursorLocation(node, node.childNodes.length);
					this.editor.execCommand('mceInsertContent', false, ZCO_BEGIN_TAG);
					// this.editor.execCommand('mceInsertContent', false, ZCO_END_TAG);
          this.editor.focus();
          this.editor.selection.setCursorLocation(node, node.childNodes.length);
          setTimeout(() => {
            node = this.editor.selection.getNode()
            console.log('nextEditableNode', node.lastChild);
            this.editor.selection.setCursorLocation(node.lastChild, 0);
            this.editor.focus();
          })
					return false;
				} else {
					const node = this.editor.selection.getNode();
					this.editor.selection.setCursorLocation(node.parentNode, 0);
					this.editor.execCommand('mceInsertContent', false, ZCO_BEGIN_TAG);
					return false;
				}
			}
			if (e.keyCode === 13 || this.editor.selection.getNode().tagName === 'SPAN') {
				e.preventDefault();
				e.stopPropagation();
				e.stopImmediatePropagation();
				return false;
			}

			if ([37, 39].includes(e.keyCode)) return true;

			let value = this.editor.getContent({ format: 'text' });
			value = value.replace(/(<|&lt;)br\s*\/*(>|&gt;)/g, '');
			if (value.length + 1 > this.maxlength) {
				e.preventDefault();
				e.stopPropagation();
				e.stopImmediatePropagation();
				return false;
			}
		},

		handleInit(evt, editor) {
			var allowedKeys = [8, 16, 17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 46];
			this.editor = editor;
			this.$nextTick(() => {
				this.parse(this.value);
				this.editor.mode.set(this.showDetail ? 'readonly' : 'design');
			});
			editor.on('keydown KeyUp', e => {
				// console.log('keydown KeyUp', editor.selection.getNode().tagName); // SPAN
				if ([13, 38, 40].includes(e.keyCode)) {
					e.preventDefault();
					e.stopPropagation();
					e.stopImmediatePropagation();
					return false;
				}
				if (allowedKeys.indexOf(e.keyCode) != -1) return true;
				if (e.ctrlKey) return true;
				let value = this.editor.getContent({ format: 'text' });
				value = value.replace(/(<|&lt;)br\s*\/*(>|&gt;)/g, '');
				if (value.length + 1 > this.maxlength) {
					e.preventDefault();
					e.stopPropagation();
					e.stopImmediatePropagation();
					return false;
				}
				return true;
			});
			editor.on('input', e => {
				console.log('input', e);
				this.handleUpdate();
			});
			editor.on('change', e => {
				this.handleUpdate();
			});
			editor.on('Undo Redo', e => {
				if ([13, 38, 40].includes(e.keyCode)) {
					e.preventDefault();
					e.stopPropagation();
					e.stopImmediatePropagation();
					return false;
				}
				if (allowedKeys.indexOf(e.keyCode) != -1) return true;
				let value = this.editor.getContent({ format: 'text' });
				value = value.replace(/(<|&lt;)br\s*\/*(>|&gt;)/g, '');
				if (value.length > this.maxlength) {
					e.preventDefault();
					e.stopPropagation();
					e.stopImmediatePropagation();
					return false;
				}
				return true;
			});
		},
		handleUpdate() {
			let value = this.editor.getContent({ format: 'text' });
			value = value.replace(/(<|&lt;)br\s*\/*(>|&gt;)/g, '');
			if (!value) {
				this.$emit('input', '');
				return;
			}
			const length = value.length;
			if (this.maxlength && length <= this.maxlength) {
				//   setEditorText(value);
				this.$emit('input', value);
				this.parsedValue = this.editor.getContent({ format: 'html' });
			} else {
				// this.parsedValue = value.substring(0, this.maxlength);
				// this.$emit('input', this.parsedValue);
				// const node = this.editor.selection.getNode()
				// console.log('node', node, node.textContent, this.maxlength - length);
				let bookmark = this.editor.selection.getBookmark();
				this.editor.setContent(this.parsedValue);
				this.editor.selection.moveToBookmark(bookmark);
        this.editor.execCommand('mceCleanup');
			}
		},

		parse(str) {
			if (!str) {
				return;
			}
			const pattern = /({{[^{}]+}})|([^{}]+)/g;

			const matches = str.match(pattern);

			const result = matches.map(match => {
				if (match.startsWith('{{') && match.endsWith('}}')) {
					// const text = match.slice(2, -2);
					return { text: match, type: 'key' };
				} else {
					return { text: match, type: 'text' };
				}
			});
			result.map(item => {
				if (item.type === 'key') {
					this.insertKeyword(item.text);
				} else {
					this.insertText(item.text);
				}
			});
			if (result[result.length - 1]?.type === 'key') {
				// this.editor.execCommand('mceInsertContent', false, ZCO_END_TAG);
			}
		},

		insertText(insertText) {
			if (insertText && this.editor) {
				let value = this.editor.getContent({ format: 'text' });
				value = value.replace(/(<|&lt;)br\s*\/*(>|&gt;)/g, '');
				if (value.length + insertText.length <= this.maxlength) {
					this.editor.execCommand('mceInsertContent', false, insertText);
				}
			}
		},

		insertKeyword(insertText) {
			if (insertText && this.editor) {
				let value = this.editor.getContent({ format: 'text' });
				value = value.replace(/(<|&lt;)br\s*\/*(>|&gt;)/g, '');
				if (value.length + insertText.length > this.maxlength) {
					return;
				}
				let tag = this.formatTag(insertText);
				this.editor.execCommand('mceInsertContent', false, tag);
			}
		},

		formatTag(text) {
			let tag = ZCO_TAG;
			let subs = text.split('_');
			if (subs.length > 1) {
				const text2 = '_' + subs[subs.length - 1].split('}')[0];
				subs.splice(subs.length - 1, 1);
				let text1 = subs.join('_');
				tag = tag.replace(/ZCO_TAG_TEXT1/g, text1);
				tag = tag.replace(/ZCO_TAG_TEXT2/g, text2);
			} else {
				tag = ZCO_TAG_2.replace(/ZCO_TAG_TEXT1/g, text);
			}

			return tag;
		}
	}
};
</script>

<style lang="less">
.mce-hide {
	/* visibility: hidden; */
	width: 0;
	max-width: 0;
	height: 0;
	max-height: 0;
	display: inline-flex;
	color: #00000000;
	width: 0;
	max-width: 0;
	height: 0;
	max-height: 0;
	display: inline-flex;
	white-space: nowrap;
	flex-wrap: nowrap;
	overflow: hidden;
}
.tinymce-input {
	border: 1px solid #dcdfe6;
	border-radius: 4px;
	padding: 0 15px;
	height: 36px;
	outline: none;
	max-height: 36px;
	background: #ffffff;
	line-height: 36px;
	box-sizing: border-box;
	font-size: 14px;
	overflow: hidden;
	white-space: normal;
	width: calc(100% - 54px);

	p {
		margin: 0;
		padding: 0;
		white-space: nowrap;
		width: 100%;
		// position: absolute;
		// left: 0;
		overflow-x: auto;
		display: block;
	}

	.el-tag.el-tag--info {
		margin: 0 2px 9px 2px;
	}
}
.tinymce-input:not([dir='rtl'])[data-mce-placeholder]:not(.mce-visualblocks)::before {
	left: 15px !important;
	color: #c0c0c0;
}
.mce-content-body[data-mce-placeholder].mce-edit-focus::before {
	content: '' !important;
}
.mceNonEditable {
	pointer-events: none;
	user-select: none;
	outline: none !important;
}
</style>
